unit Map_Storage;

interface

uses Constants, ImpactSprite, Recognition, Scripts, Supply,Windows, Messages,
SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, AsphyreDef, StrUtils;

type
  TDecoration=class
    Home:boolean;

    ImageName:string;
    ImageAngle:double;
    x,y:double;
    Trigger:boolean;
    TriggerScript:TScript;

    IsRect:boolean;
    CollisionSize:TPoint2;
    CollisionRad:real;
  end;

  TMap=class
  private
    FScripts:array of TScript;
    FDecorations:array of TDecoration;
    function GetDecoration(Index:integer):TDecoration;
    function GetDecoraionCount:integer;
    function GetScript(Index:integer):TScript;
    function GetScriptCount:integer;
  public
    LandMatrix:array[1..8] of array[1..8] of string;
    procedure AddDecoration(ADec:TDecoration);
    procedure RemoveDecoration(ADec:TDecoration);
    procedure AddScript(AScr:TScript);
    procedure SaveMission(FileName:string);
    procedure LoadMission(FileName:string);
    function SearchScript(Name:string):TScript;
    property Decorations[Index: Integer]:TDecoration read GetDecoration;
    property DecorationCount:integer read GetDecoraionCount;
    property Scripts[Index: Integer]:TScript read GetScript;
    property ScriptCount:integer read GetScriptCount;
  end;

function Decoration(AImageName:string;ax,ay:real;ATrigger:boolean;ATriggerScript:TScript;
  AIsRect:boolean;ACollisionSize:TPoint2;ACollisionRad:real;AHome:boolean;AImageAngle:double):TDecoration;

implementation

uses Main, AsphyreSprite, Scenes;

function Decoration(AImageName:string;ax,ay:real;ATrigger:boolean;ATriggerScript:TScript;
  AIsRect:boolean;ACollisionSize:TPoint2;ACollisionRad:real;AHome:boolean;AImageAngle:double):TDecoration;
begin
  Result:=TDecoration.Create;
  Result.ImageName:=AImageName;
  Result.x:=ax;
  Result.y:=ay;
  Result.Trigger:=ATrigger;
  Result.TriggerScript:=ATriggerScript;
  Result.IsRect:=AIsRect;
  Result.Home:=AHome;
  Result.CollisionRad:=ACollisionRad;
  Result.CollisionSize:=ACollisionSize;
  Result.ImageAngle:=AImageAngle;
end;

function TMap.GetScript(Index:integer):TScript;
begin
  result:=FScripts[Index];
end;

function TMap.GetScriptCount:integer;
begin
  Result:=Length(FScripts)
end;

function TMap.GetDecoraionCount:integer;
begin
  Result:=Length(FDecorations);
end;

function TMap.GetDecoration(Index:integer):TDecoration;
begin
  result:=FDecorations[Index];
end;

function TMap.SearchScript(Name:string):TScript;
var
i:integer;
begin
  for i := 0 to ScriptCount-1 do
  if FScripts[i].Name=Name then
  begin
    result:=FScripts[i];
    exit;
  end;
end;

procedure TMap.AddScript(AScr:TScript);
var
i:integer;
begin
  i:=length(FScripts);
  SetLength(FScripts,i+1);
  FScripts[i]:=AScr;
end;

procedure TMap.AddDecoration(ADec:TDecoration);
var
i:integer;
begin
  i:=length(FDecorations);
  SetLength(FDecorations,i+1);
  FDecorations[i]:=ADec;
end;

procedure TMap.RemoveDecoration(ADec:TDecoration);
var
i,j:integer;
Temp:TDecoration;
begin
  j:=-1;
  for i := 0 to DecorationCount-1 do
  begin
    if FDecorations[i]=ADec then
    begin
      j:=i;
      break;
    end;
  end;
  if j>-1 then
  begin
    Temp:=FDecorations[j];
    for i := j to DecorationCount-2 do
    begin
      FDecorations[i]:=FDecorations[i+1];
    end;
    Temp.Free;
    SetLength(FDecorations,DecorationCount-1);
  end;
end;

procedure TMap.LoadMission(FileName:string);
var
i,c1,c2:integer;
S:TStringList;
str:string;
StrArr:array[0..20] of string;
AScript:TScript;
begin
  S:=TStringList.Create;
  S.LoadFromFile(FileName);
  str:=s.Text;
  S.Free;
  while Pos('//',str)>0 do
  Delete(str,Pos('//',str),PosEx(#13#10,str,Pos('//',str))-Pos('//',str)+2);
  while Pos(#13#10,str)>0 do
  Delete(str,Pos(#13#10,str),2);
  while pos('map<<',str)>0 do
  begin
    c1:=pos('map<<',str);
    Delete(str,c1,5);
    for i := 0 to 62 do
    begin
      c2:=PosEx(',',str,c1);
      LandMatrix[i mod 8+1, i div 8+1]:=Copy(str,c1,c2-c1);
      Delete(str,c1,c2-c1+1);
    end;
    c2:=PosEx('>>',str,c1);
    LandMatrix[8,8]:=Copy(str,c1,c2-c1);
    Delete(str,c1,c2-c1+2);
  end;
  while pos('script<<',str)>0 do
  begin
    c1:=pos('script<<',str);
    Delete(str,c1,8);
    for i := 0 to 3 do
    begin
      c2:=PosEx(',',str,c1);
      StrArr[i]:=Copy(str,c1,c2-c1);
      Delete(str,c1,c2-c1+1);
    end;
    c2:=PosEx('>>',str,c1);
    StrArr[4]:=Copy(str,c1,c2-c1);
    Delete(str,c1,c2-c1+2);
    AddScript(Script(StrArr[0],StrArr[4],
      StrToFloat(StrArr[1]),StrToBool(StrArr[3]),StrToBool(StrArr[2])));
  end;
  while pos('Decoration<<',str)>0 do
  begin
    c1:=pos('Decoration<<',str);
    Delete(str,c1,12);
    for i := 0 to 7 do
    begin
      c2:=PosEx(',',str,c1);
      StrArr[i]:=Copy(str,c1,c2-c1);
      Delete(str,c1,c2-c1+1);
    end;
    if StrToBool(StrArr[5]) then
    for i := 8 to 11 do
    begin
      c2:=PosEx(',',str,c1);
      StrArr[i]:=Copy(str,c1,c2-c1);
      Delete(str,c1,c2-c1+1);
    end;
    c2:=PosEx('>>',str,c1);
    StrArr[i]:=Copy(str,c1,c2-c1);
    Delete(str,c1,c2-c1+2);
    if StrArr[4]<>'' then
    AScript:=SearchScript(StrArr[4]);
    if not StrToBool(StrArr[5]) then
    AddDecoration(Decoration(StrArr[0],StrToFloat(StrArr[1]),
      StrToFloat(StrArr[2]),StrToBool(StrArr[3]),
      AScript,StrToBool(StrArr[5]),Point2(0,0),
      StrToFloat(StrArr[6]),StrToBool(StrArr[7]),StrToInt(StrArr[8])/180*pi))
    else
    AddDecoration(Decoration(StrArr[0],StrToFloat(StrArr[1]),
      StrToFloat(StrArr[2]),StrToBool(StrArr[3]),
      AScript,StrToBool(StrArr[5]),Point2(StrToFloat(StrArr[6]),
      StrToFloat(StrArr[7])),0,
      StrToBool(StrArr[11]),StrToInt(StrArr[12])/180*pi));
  end;
  while pos('NPC<<',str)>0 do
  begin
    c1:=pos('NPC<<',str);
    Delete(str,c1,5);
    for i := 0 to 3 do
    begin
      c2:=PosEx(',',str,c1);
      StrArr[i]:=Copy(str,c1,c2-c1);
      Delete(str,c1,c2-c1+1);
    end;
    c2:=PosEx('>>',str,c1);
    StrArr[4]:=Copy(str,c1,c2-c1);
    Delete(str,c1,c2-c1+2);
    with TGameScene(Scene) do
    with TNPC.Create(SpriteEngine,StrToFloat(StrArr[0]),
      StrToFloat(StrArr[1]),StrArr[2]) do
    begin
      Angle:=StrToFloat(StrArr[3])/180*pi;
      Health:=StrToFloat(StrArr[4])/100*MaxHealth;
      SetAngleToPart(Angle*40.6);
    end;
  end;
  while pos('Object<<',str)>0 do
  begin
    c1:=pos('Object<<',str);
    Delete(str,c1,8);
    for i := 0 to 14 do
    begin
      c2:=PosEx(',',str,c1);
      StrArr[i]:=Copy(str,c1,c2-c1);
      Delete(str,c1,c2-c1+1);
    end;
    if StrArr[14]='quad' then
    for i := 15 to 15 do
    begin
      c2:=PosEx(',',str,c1);
      StrArr[i]:=Copy(str,c1,c2-c1);
      Delete(str,c1,c2-c1+1);
    end;
    c2:=PosEx('>>',str,c1);
    StrArr[i]:=Copy(str,c1,c2-c1);
    Delete(str,c1,c2-c1+2);
    with TStaticObject.Create(SpriteEngine,StrToFloat(StrArr[0]),
      StrToFloat(StrArr[1]),StrToBool(StrArr[2]),
      StrArr[3],StrToBool(StrArr[4]),StrToFloat(StrArr[5]),
      StrToFloat(StrArr[6]),StrToFloat(StrArr[7])) do
    begin
      DoCollision:=true;
      Angle:=StrToFloat(StrArr[8])/180*pi;
      MaxHealth:=StrToFloat(StrArr[9]);
      Health:=StrToFloat(StrArr[10]);
      CollideUnstopable:=StrToBool(StrArr[12]);
      StaticAngle:=StrToBool(StrArr[13]);
      if StrArr[14]='quad' then
      begin
        CollideMethod:=cmQuadrangle;
        ChangeCollideAttr(cmQuadrangle,StrToFloat(StrArr[15]),
          StrToFloat(StrArr[16]),StrToFloat(StrArr[11]));
      end
      else
      begin
        CollideMethod:=cmRadius;
        ChangeCollideAttr(cmRadius,StrToFloat(StrArr[15]),
          StrToFloat(StrArr[15]),StrToFloat(StrArr[11]));
      end;
    end;
  end;
end;

procedure TMap.SaveMission(FileName:string);
var
str,s1:string;
i:integer;
S:TStringList;
begin
  str:='map<<';
  for i := 0 to 62 do
  begin
    if i mod 8=0 then
    str:=str+#13#10;
    str:=str+LandMatrix[i mod 8+1, i div 8+1]+',';
  end;
  str:=str+LandMatrix[8,8]+'>>'+#13#10;
  for i := 0 to ScriptCount-1 do
  begin
    str:=str+'script<<'+Scripts[i].Name+','+FloatToStrF(Scripts[i].WaitStart,ffFixed,5,2)
      +','+BoolToStr(Scripts[i].Global)+','+BoolToStr(Scripts[i].OneTime)+','+
      Scripts[i].s+'>>'+#13#10;
  end;
  for i := 0 to DecorationCount-1 do
  begin
    s1:='';
    if Decorations[i].Trigger then
    s1:=Decorations[i].TriggerScript.Name;
    if not Decorations[i].IsRect then
    str:=str+'Decoration<<'+Decorations[i].ImageName+','+
      FloatToStrF(Decorations[i].x,ffFixed,5,2)+','+
      FloatToStrF(Decorations[i].y,ffFixed,5,2)+','
      +BoolToStr(Decorations[i].Trigger)+','+s1+
      ','+BoolToStr(Decorations[i].IsRect)+','+
      FloatToStrF(Decorations[i].CollisionRad,ffFixed,5,2)+','+
      BoolToStr(Decorations[i].Home)+','+
      IntToStr(round(Decorations[i].ImageAngle*180/pi))+'>>'+#13#10;
  end;
  for i := 0 to SpriteEngine.Count-1 do
  if SpriteEngine[i] is TNPC then
  begin
    str:=str+'NPC<<'+FloatToStrF(SpriteEngine[i].x,ffFixed,5,2)+','+
      FloatToStrF(SpriteEngine[i].y,ffFixed,5,2)+','+
      TNPC(SpriteEngine[i]).StaticConstants.Name+','+
      IntToStr(round(SpriteEngine[i].Angle*180/pi))+','+
      FloatToStrF(TNPC(SpriteEngine[i]).Health/TNPC(SpriteEngine[i]).MaxHealth*
        100,ffFixed,5,2)+'>>'+#13#10;
  end;
  for i := 0 to SpriteEngine.Count-1 do
  if SpriteEngine[i] is TStaticObject then
  begin
    if SpriteEngine[i].CollideMethod=cmRadius then
    str:=str+'Object<<'+FloatToStrF(SpriteEngine[i].x,ffFixed,5,2)+','+
      FloatToStrF(SpriteEngine[i].y,ffFixed,5,2)+','+
      BoolToStr(SpriteEngine[i].Visible)+','+
      SpriteEngine[i].ImageName+','+
      BoolToStr(TStaticObject(SpriteEngine[i]).Firing)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).FireSpeed,ffFixed,5,2)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).DeathCount,ffFixed,5,2)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).incDeath,ffFixed,5,2)+','+
      IntToStr(round(SpriteEngine[i].Angle*180/pi))+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).MaxHealth,ffFixed,5,2)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).Health,ffFixed,5,2)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).Mass,ffFixed,5,2)+','+
      BoolToStr(TStaticObject(SpriteEngine[i]).CollideUnstopable)+','+
      BoolToStr(TStaticObject(SpriteEngine[i]).StaticAngle)+',radius,'+
      FloatToStrF(SpriteEngine[i].CollideRadius,ffFixed,5,2)+'>>'
      else
    str:=str+'Object<<'+FloatToStrF(SpriteEngine[i].x,ffFixed,5,2)+','+
      FloatToStrF(SpriteEngine[i].y,ffFixed,5,2)+','+
      BoolToStr(SpriteEngine[i].Visible)+','+
      SpriteEngine[i].ImageName+','+
      BoolToStr(TStaticObject(SpriteEngine[i]).Firing)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).FireSpeed,ffFixed,5,2)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).DeathCount,ffFixed,5,2)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).incDeath,ffFixed,5,2)+','+
      IntToStr(round(SpriteEngine[i].Angle*180/pi))+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).MaxHealth,ffFixed,5,2)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).Health,ffFixed,5,2)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).Mass,ffFixed,5,2)+','+
      BoolToStr(TStaticObject(SpriteEngine[i]).CollideUnstopable)+','+
      BoolToStr(TStaticObject(SpriteEngine[i]).StaticAngle)+',quad,'+
      FloatToStrF(TStaticObject(SpriteEngine[i]).QuadrangleSize.x,ffFixed,5,2)+','+
      FloatToStrF(TStaticObject(SpriteEngine[i]).QuadrangleSize.y,ffFixed,5,2)+'>>'+#13#10;
  end;
  s:=TStringList.Create;
  s.text:=str;
  s.SaveToFile(FileName);
  s.Free;
end;

end.
